﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;

namespace Analyzer
{
    public class BoolToVisibilityConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Visibility inCaseOfFalse = Visibility.Collapsed;
            try
            {
                inCaseOfFalse = (Visibility)parameter;
            }
            catch (InvalidCastException) { }
            catch (NullReferenceException) { }
            if ((Boolean)value == true)
            {
                return Visibility.Visible;
            }
            else if ((Boolean)value == false)
            {
                return inCaseOfFalse;
            }
            else
            {
                Debug.WriteLine("Analyzer.BoolToVisibilityConverter: " +
                    "A Convert bemenő paramétere nem Boolean típusú, hanem " +
                    value.GetType().ToString());
                throw new ArgumentException("Analyzer.BoolToVisibilityConverter: " +
                    "A Convert bemenő paramétere nem Boolean típusú, hanem " +
                    value.GetType().ToString(), "moduleRelation");
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException("BoolToVisibilityConverter nem támogatja a ConvertBack műveletet!");
        }

        #endregion
    }

    public class DebugConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            //VS10-ben összeomlasztja a designert Debugger.Break();
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }

        #endregion
    }

    public class StringToListStringConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is String == false)
                return Binding.DoNothing;
            List<String> lValue = value as List<String>;
            return Binding.DoNothing;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class DoubleToPercentStringConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            double doubleValue;
            if (value is double == false)
                return Binding.DoNothing;
            doubleValue = (double)value;
            doubleValue *= 100.0;
            string convertedValue = doubleValue.ToString();
            if (convertedValue.Length > 5)
                convertedValue = convertedValue.Substring(0, 5);
            return convertedValue;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    /// <summary>
    /// Egy 0 és 1 közötti számot konvertál 0 és 100 közötti számmá és vissza.
    /// </summary>
    public class DoublePercentConverter : IValueConverter
    {
        public static object ConvertStatic(object value, Type targetType, object parameter, CultureInfo culture)
        {
            double valueD = double.NaN;
            try
            {
                valueD = (double)value;
            }
            catch (InvalidCastException) { return Binding.DoNothing; }

            return valueD * 100.0;
        }

        #region IValueConverter Members

        /// <summary>
        /// Egy 0 és 1 közötti számot konvertál 0 és 100 közötti számmá.
        /// </summary>
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return ConvertStatic(value, targetType, parameter, culture);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string valueS;
            try
            {
                valueS = (string)value;
            }
            catch (InvalidCastException) { valueS = "failed"; }
            double valueD;
            try
            {
                valueD = (double)value;
            }
            catch (InvalidCastException) { valueD = double.NaN; }
            if (valueS == "failed" && valueD == double.NaN)
                return valueD;

            if (valueS != "failed")
            {
                try
                {
                    return double.Parse(valueS) / 100.0;
                }
                catch (FormatException) { return double.NaN; }
                catch (OverflowException) { return double.NaN; }
            }
            else if (valueD != double.NaN)
            {
                return valueD / 100.0;
            }
            else
                return Binding.DoNothing;
        }

        #endregion
    }

    public class CutDoubleDoubleConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }

        /// <summary>
        /// Adott tizedesjegy-számúra vágja a megadott double típusú értéket.
        /// </summary>
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            int numberOfDigits = 2;
            int nOD = -1;
            if (parameter != null)
            {
                try
                {
                    nOD = int.Parse((string)parameter);
                }
                catch (InvalidCastException) { }
                catch (FormatException) { }
                catch (OverflowException) { }
            }
            if (nOD != -1)
                numberOfDigits = nOD;
            double valueD = (double)value;
            double c = Math.Pow(10.0, numberOfDigits);
            valueD *= c;
            valueD = Math.Floor(valueD);
            valueD /= c;

            return valueD;
        }

        #endregion
    }

    public class StringDoubleConverter : IValueConverter
    {
        public static object ConvertStatic(object value, Type targetType, object parameter, CultureInfo culture)
        {
            double valueD = double.NaN;
            try
            {
                valueD = (double)value;
            }
            catch (InvalidCastException) { return "Nem szám!"; }

            return valueD.ToString();
        }

        public static object ConvertBackStatic(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string valueS = string.Empty;
            try
            {
                valueS = (string)value;
            }
            catch (InvalidCastException) { return Binding.DoNothing; }

            double valueD = double.NaN;
            try
            {
                valueD = double.Parse(valueS);
            }
            catch (FormatException) { return double.NaN; }
            catch (OverflowException) { return double.NaN; }

            return valueD;
        }

        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return ConvertStatic(value, targetType, parameter, culture);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return ConvertBackStatic(value, targetType, parameter, culture);
        }

        #endregion
    }

    public class DoubleStringConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return StringDoubleConverter.ConvertBackStatic(value, targetType, parameter, culture);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return StringDoubleConverter.ConvertStatic(value, targetType, parameter, culture);
        }

        #endregion
    }

    public class NullableIntStringConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            int? valueI = null;
            try
            {
                if (value is int? == false)
                    throw new InvalidCastException();
                valueI = value as int?;
            }
            catch (InvalidCastException) { return "Nem szám!"; }

            return valueI.ToString();
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string valueS = string.Empty;
            try
            {
                valueS = (string)value;
            }
            catch (InvalidCastException) { return null; }

            int valueI;
            try
            {
                valueI = int.Parse(valueS);
            }
            catch (FormatException) { return null; }
            catch (OverflowException) { return null; }

            return (int?)valueI;
        }

        #endregion
    }

    public class UintDoubleConverter : IValueConverter
    {
        public static object StaticConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            uint valueUi;
            try
            {
                valueUi = (uint)Math.Floor((double)value);
            }
            catch (InvalidCastException) { return -1; }
            catch (ArgumentNullException) { return -1; }
            return valueUi;
        }

        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }

        public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return StaticConvertBack(value, targetType, parameter, culture);
        }

        #endregion
    }

    public class NullableUintDoubleConverter : UintDoubleConverter
    {
        #region IValueConverter Members

        public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            uint? valueUi = (uint?)UintDoubleConverter.StaticConvertBack(value, targetType, parameter, culture);
            if (valueUi.Value < 0)
                return null;
            else
                return valueUi;
        }

        #endregion
    }

    /// <remarks>
    /// http://stackoverflow.com/questions/397556/wpf-how-to-bind-radiobuttons-to-an-enum
    /// </remarks>
    public class EnumBooleanConverter : IValueConverter
    {
        #region IValueConverter Members
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string parameterString = parameter as string;
            if (parameterString == null)
                return DependencyProperty.UnsetValue;

            if (Enum.IsDefined(value.GetType(), value) == false)
                return DependencyProperty.UnsetValue;

            object parameterValue = Enum.Parse(value.GetType(), parameterString);

            return parameterValue.Equals(value);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string parameterString = parameter as string;
            if (parameterString == null)
                return DependencyProperty.UnsetValue;

            return Enum.Parse(targetType, parameterString);
        }
        #endregion
    }

    public class StringToBrushConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string convertedValue = value as string;
            if (convertedValue == null)
                return Binding.DoNothing;
            //string wpfColor = "#FF" + convertedValue.Substring(1, convertedValue.Length - 1);
            Color color = new Color();
            try
            {
                byte r;
                byte.TryParse(convertedValue.Substring(1, 2), out r);
                color.R = r;
                byte g;
                byte.TryParse(convertedValue.Substring(3, 2), out g);
                color.G = g;
                byte b;
                byte.TryParse(convertedValue.Substring(5, 2), out b);
                color.B = b;
            }
            catch (ArgumentException)
            {
                return Binding.DoNothing;
            }
            return new SolidColorBrush(color);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class StringUriConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Uri uriValue = value as Uri;
            if (uriValue == null)
                return Binding.DoNothing;
            return uriValue.LocalPath;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string stringValue;
            try
            {
                stringValue = (string)value;
            }
            catch (InvalidCastException)
            {
                return Binding.DoNothing;
            }
            try
            {
                return new Uri(stringValue);
            }
            catch (UriFormatException)
            {
                return Binding.DoNothing;
            }
        }

        #endregion
    }

    public class IntToBoolConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            int intValue = -1;
            try
            {
                intValue = (int)value;
            }
            catch (InvalidCastException)
            {
                return Binding.DoNothing;
            }
            return intValue > 0;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            bool boolValue = false;
            try
            {
                boolValue = (bool)value;
            }
            catch (InvalidCastException)
            {
                return Binding.DoNothing;
            }
            if (boolValue == true)
                return 1;
            else
                return 0;
        }

        #endregion IValueConverter Members
    }

    public class TitleConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string sValue = null;
            try
            {
                sValue = (string)value;
            }
            catch (InvalidCastException) { }
            string appName = "";
            try
            {
                appName = (string)parameter;
            }
            catch (InvalidCastException) { return Binding.DoNothing; }
            catch (NullReferenceException) { return Binding.DoNothing; }
            return sValue == null ? appName : sValue + " - " + appName;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

}
